home *** CD-ROM | disk | FTP | other *** search
- #import "FinderManager.h"
- #import "WorkspaceManager.h"
- #import <appkit/Application.h>
- #import <appkit/NXBrowser.h>
- #import <appkit/NXBrowserCell.h>
- #import <appkit/Text.h>
- #import <appkit/Matrix.h>
- #import <appkit/publicWraps.h>
- #import <appkit/PopUpList.h>
- #import <appkit/Matrix.h>
- #import <objc/Storage.h>
- #import <regex.h>
- #import <strings.h>
- #import <libc.h>
-
- #define MAXFINDERCELLLEN 80
- extern void NuGets() ;
-
- @implementation FinderManager: Object
- { id finderLineTextField,
- findText,
- replaceText,
- caseSwitch,
- regExpSwitch,
- selScopeSwitch,
- lineNumBrowser ;
- }
-
- - (int)browser:sender fillMatrix:matrix inColumn:(int)column ;
- { // delegate method for browser object
- if([[NXApp mainWindow] isKindOf: [WorkspaceManager class]])
- return [[[NXApp mainWindow] lineList] count] ;
- return 0 ;
- }
-
- - browser:sender loadCell:cell atRow:(int)row inColumn:(int)column ;
- { if([[NXApp mainWindow] isKindOf: [WorkspaceManager class]])
- { int i,lineNum, charNum ;
- id theView ;
- char buf1[MAXFINDERCELLLEN+10], buf2[MAXFINDERCELLLEN + 17] ;
- theView = [[NXApp mainWindow] textView] ;
- lineNum = * (int *) [[[NXApp mainWindow] lineList] elementAt: row] ;
- charNum = [theView positionFromLine: lineNum] ;
- [theView getSubstring: buf1 start: charNum length: MAXFINDERCELLLEN] ;
- for(i = 0 ; i < MAXFINDERCELLLEN ; i++)
- { if(buf1[i] == '\n') // don't grab more than 1 line...
- { buf1[i] = '\0' ;
- break ;
- }
- }
- buf1[i] = '\0' ; // make sure null terminated!
- sprintf(buf2,"%-5d %s",lineNum,buf1) ;
- [cell setStringValue: buf2] ;
- [cell setLeaf:YES] ;
- }
- return self ;
- }
-
- - find: (char *) text regEx: (BOOL) regEx caseSensitive: (BOOL) caseSensitive inSelection: (BOOL) inSelection ;
- { // find the next occurence of "text" in the textview of the
- // current mainWindow, provided in inherits from WorkspaceManager. Text may contain
- // a regular expression. The search may be case sensitive. The search may be
- // confined to the current selection. Returns nil if text is not found, else
- // makes the text the current selection.
- id myWin = [lineNumBrowser window] ;
- if([[NXApp mainWindow] isKindOf: [WorkspaceManager class]])
- { int origLen, newLen ;
- long firstStart, lastStart ;
- BOOL wrapped = NO ;
- char textBuf[1024] ;
- origLen = newLen = strlen(text) ;
- if(!regEx)
- newLen *= 2 ; // not a rexp:leave room to quote everything
- { int i,j ;
- char specialChars[] = "[]^*$\\." ;
- struct regex *ex ;
- NXStream *aStream ;
- NXSelPt start, end ;
- char regexText[newLen+1] ;
- id aView ;
- if(!regEx)
- { for(i = 0,j = 0 ; text[i] ; i++,j++)
- { if(index(specialChars,text[i])) // if a special char,
- regexText[j++] = '\\' ; // then turn off its special meaning by
- regexText[j] = text[i] ; // quoting it.
- }
- regexText[j] = '\0' ;
- }
- else
- strcpy(regexText,text) ;
- ex = re_compile(regexText,caseSensitive) ;
- aView = [[NXApp mainWindow] textView] ;
- [aView getSel: &start :&end] ;
- if(!inSelection) // scope is entire file
- { aStream = [[[NXApp mainWindow] textView] stream] ;
- // search begins after current selection
- firstStart = lastStart = (long) end.cp ;
- }
- else // scope is selection only
- { int len = end.cp - start.cp ;
- { char aBuf[len + 1] ;
- aStream = NXOpenMemory(NULL, 0, NX_READWRITE) ;
- [aView getSubstring: aBuf start: start.cp length: len] ;
- NXWrite(aStream, aBuf, len) ;
- // search begins at beginning of stream
- firstStart = lastStart = 0 ;
- }
- }
- NXSeek(aStream, lastStart, NX_FROMSTART) ;
- NuGets(aStream,textBuf) ;
- do
- { if(re_match(textBuf,ex))
- { if(inSelection)
- { [aView setSel:(int) (lastStart + ex->start -
- (int) textBuf + start.cp)
- :(int) (lastStart + ex->end)-
- (int) textBuf + start.cp] ;
- NXCloseMemory(aStream, NX_FREEBUFFER) ;
- }
- else
- [aView setSel:(int) (lastStart + ex->start - (int) textBuf)
- :(int) (lastStart + ex->end)- (int) textBuf] ;
- [aView scrollSelToVisible] ;
- free(ex) ;
- [[NXApp mainWindow] makeKeyAndOrderFront: self] ;
- return self ;
- }
- if(NXAtEOS(aStream)) // wrap around to beginning
- { NXSeek(aStream, 0L,NX_FROMSTART) ;
- wrapped = YES ;
- }
- lastStart = NXTell(aStream) ;
- NuGets(aStream,textBuf) ;
- } while(!(wrapped && (lastStart >= firstStart))) ;
- free(ex) ;
- if(inSelection)
- NXCloseMemory(aStream, NX_FREEBUFFER) ;
- NXBeep() ;
- [myWin setTitle: "Not Found"] ;
- NXPing() ;
- usleep(500000) ;
- [myWin setTitle: "Find"] ;
- return nil ;
- }
- }
- else
- { NXBeep() ;
- [myWin setTitle: "What window?"] ;
- NXPing() ;
- usleep(500000) ;
- [myWin setTitle: "Find"] ;
- }
- return self ;
- }
-
-
- - finderAddLine: sender ;
- { // add the current line to the list of lines
- if([[NXApp mainWindow] isKindOf: [WorkspaceManager class]])
- { id theView ;
- NXSelPt start, end ;
- theView = [[NXApp mainWindow] textView] ;
- [theView getSel: &start :&end] ;
- [[NXApp mainWindow] addToLineList: [theView lineFromPosition: start.cp]] ;
- [lineNumBrowser loadColumnZero] ;
- }
- return self ;
- }
-
- - finderBrowserHit: sender ;
- { NXEvent * anEvent ;
- anEvent = [NXApp currentEvent] ;
- if([[NXApp mainWindow] isKindOf: [WorkspaceManager class]])
- /* if you want to fire on double clicks, use this:
- if([[NXApp mainWindow] isKindOf: [WorkspaceManager class]]
- && anEvent->data.mouse.click == 2) */
- { char aBuf[MAXFINDERCELLLEN+17] ;
- int lineNum ;
- [lineNumBrowser setPathSeparator: ' '] ;
- [lineNumBrowser getPath: aBuf toColumn: 1] ;
- if(sscanf(aBuf,"%d",&lineNum))
- { id aView ;
- aView = [[NXApp mainWindow] textView] ;
- [aView setSel: [aView positionFromLine: lineNum]
- : [aView positionFromLine: lineNum + 1]] ;
- [aView scrollSelToVisible] ;
- [[NXApp mainWindow] makeKeyAndOrderFront: self] ;
- }
- }
- return self ;
- }
-
- - finderCurrent: sender ;
- { // put line number of beginning of selection into
- // the finderLineTextField
- id aView ;
- if([[NXApp mainWindow] isKindOf: [WorkspaceManager class]])
- { NXSelPt start,end ;
- aView = [[NXApp mainWindow] textView] ;
- [aView getSel: &start :&end] ;
- [finderLineTextField setIntValue: [aView lineFromPosition: start.cp]] ;
- }
- return self ;
- }
-
- - finderGoTo: sender ;
- { // set selection at beginning of line indicated by
- // finderLineTextField
- id aView ;
- if([[NXApp mainWindow] isKindOf: [WorkspaceManager class]])
- { int pos1, pos2, lineNum ;
- aView = [[NXApp mainWindow] textView] ;
- pos1 = [aView positionFromLine:lineNum = [finderLineTextField intValue]] ;
- pos2 = [aView positionFromLine: lineNum + 1] ;
- [aView setSel:pos1 :pos2] ;
- [aView scrollSelToVisible] ;
- [finderLineTextField selectText: self] ;
- [[NXApp mainWindow] makeKeyAndOrderFront: self] ;
- }
- return self ;
- }
-
- struct MenuDefs
- { @defs(Menu)
- } ;
-
- - finderNext: sender ;
- { // find the next occurence of the "find" text.
- // returns nil if unable. Note the contortions
- // needed to get the id of the current pop-up
- // list selection...the trouble is NeXT give
- // no method to obtain a Menu's Matrix
- // so have to grab it from the ivar
- struct MenuDefs *reg, *cas, *sel ;
- reg = (struct MenuDefs *) regExpSwitch ;
- cas = (struct MenuDefs *) caseSwitch ;
- sel = (struct MenuDefs *) selScopeSwitch ;
- return [self find: (char *) [findText stringValue]
- regEx: [[reg->matrix selectedCell] tag]
- caseSensitive: ![[cas->matrix selectedCell] tag]
- inSelection: [[sel->matrix selectedCell] tag]] ;
- }
-
-
-
- - finderRemLine: sender ;
- { // remove the browser-selected line from the list of lines
- if([[NXApp mainWindow] isKindOf: [WorkspaceManager class]])
- { [[NXApp mainWindow] removeFromLineList: [[lineNumBrowser matrixInColumn:0] selectedRow]] ;
- [lineNumBrowser loadColumnZero] ;
- }
- return self ;
- }
-
- - finderReplace: sender ;
- { // replace the highlighted text with the current text
- id aView ;
- if([[NXApp mainWindow] isKindOf: [WorkspaceManager class]])
- { aView = [[NXApp mainWindow] textView] ;
- [aView replaceSel: [replaceText stringValue]] ;
- }
- return self ;
- }
-
- - finderReplaceAll: sender ;
- { // replace all occurences of the find text with the replace text
- if([[NXApp mainWindow] isKindOf: [WorkspaceManager class]])
- { struct MenuDefs *sel ;
- sel = (struct MenuDefs *) selScopeSwitch ;
- if(![[sel->matrix selectedCell] tag])
- { if([self finderNext: self])
- while([self finderReplaceAndFind: self]) ;
- }
- else // scope is entire file
- { NXSelPt start, end ;
- id aView ;
- int diff ;
- diff = strlen([replaceText stringValue]) -
- strlen([findText stringValue]) ;
- aView = [[NXApp mainWindow] textView] ;
- [aView getSel:&start :&end] ;
- while([self finderNext: self])
- { end.cp += diff ;
- [self finderReplace: self] ;
- // must reset the (adjusted) selection
- [aView setSel: start.cp :end.cp] ;
- }
- }
- }
- return self ;
-
- }
-
- - finderReplaceAndFind: sender ;
- { // replace the highlighted text with the replacement text,
- // find next occurence of find text
- if([[NXApp mainWindow] isKindOf: [WorkspaceManager class]])
- { [self finderReplace: self] ;
- return [self finderNext: self] ;
- }
- return self ;
- }
-
- - findLine ;
- { return finderLineTextField ;
- }
-
- - findText ;
- { return findText ;
- }
-
- - init ;
- { // IB sends us our popupList's trigger id, not the popupLists
- // themselves
- [super init] ;
- caseSwitch = [caseSwitch target] ;
- regExpSwitch = [regExpSwitch target] ;
- selScopeSwitch = [selScopeSwitch target] ;
- return self ;
- }
-
- - lineNumBrowser ;
- { return lineNumBrowser ;
- }
-
- - setTheFindText: (char *) theText ;
- { // set the find text to theText
- [findText setStringValue: theText] ;
- return self ;
- }
-
- @end
-